home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 236_01 / bawkact.c < prev    next >
Text File  |  1989-06-05  |  9KB  |  455 lines

  1. /*
  2.     HEADER:        CUG236;
  3.     TITLE:        BAWK Actions Compiler;
  4.     DATE:        05/17/1987;
  5.     VERSION:    1.1;
  6.     FILENAME:    BAWKACT.C;
  7.     SEE-ALSO:    BAWK.C;
  8.     AUTHORS:    W. C. Colley III, B. Brodt;
  9. */
  10.  
  11. /*
  12.  * Bawk C actions compiler
  13.  */
  14. #include <stdio.h>
  15. #include "bawk.h"
  16.  
  17. /* Functions local to this module.    */
  18.  
  19. char *str_compile();
  20. int stmt_compile();
  21.  
  22. int act_compile( actbuf )
  23. char    *actbuf;    /* where tokenized actions are compiled into */
  24. {
  25.     Where = ACTION;
  26.     return stmt_compile( actbuf );
  27. }
  28.  
  29. int pat_compile( actbuf )
  30. char    *actbuf;    /* where tokenized actions are compiled into */
  31. {
  32.     Where = PATTERN;
  33.     return stmt_compile( actbuf );
  34. }
  35.  
  36. int stmt_compile( actbuf )
  37. char    *actbuf;    /* where tokenized actions are compiled into */
  38. {
  39.     /*
  40.      * Read and tokenize C actions from current input file into the
  41.      * action buffer.  Strip out comments and whitespace in the
  42.      * process.
  43.      */
  44.     char    *actptr,    /* actbuf pointer */
  45.         *cp,        /* work pointer */
  46.         buf[MAXLINELEN];/* string buffer */
  47.     int    braces,        /* counts '{}' pairs - return when 0 */
  48.         parens,        /* counts '()' pairs */
  49.         i,        /* temp */
  50.         c;        /* current input character */
  51.  
  52.     braces = parens = 0;
  53.     actptr = actbuf;
  54.     while ( (c = getcharacter()) != -1 )
  55.     {
  56.         /*
  57.          * Skip over spaces, tabs and newlines
  58.          */
  59.         if ( c==' ' || c=='\t' || c=='\n' )
  60.             continue;
  61.         if ( c=='#' )
  62.         {
  63.             /*
  64.              * Skip comments.  Comments start with a '#' and
  65.              * end at the next newline.
  66.              */
  67.             while ( (c = getcharacter()) != -1 && c!='\n' )
  68.                 ;
  69.             continue;
  70.         }
  71.  
  72.         if ( c=='{' )
  73.         {
  74.             if ( Where==PATTERN )
  75.             {
  76.                 /*
  77.                  * We're compiling a pattern. The '{' marks
  78.                  * the beginning of an action statement.
  79.                  * Push the character back and return.
  80.                  */
  81.                 ungetcharacter( '{' );
  82.                 break;
  83.             }
  84.             else
  85.             {
  86.                 /*
  87.                  * We must be compiling an action statement.
  88.                  * '{'s mark beginning of action or compound
  89.                  * statements.
  90.                  */
  91.                 ++braces;
  92.                 *actptr++ = T_LBRACE;
  93.             }
  94.         }
  95.         else if ( c=='}' )
  96.         {
  97.             *actptr++ = T_RBRACE;
  98.             if ( ! --braces )
  99.                 /*
  100.                  * Found the end of the action string
  101.                  */
  102.                 break;
  103.         }
  104.         else if ( c=='(' )
  105.         {
  106.             ++parens;
  107.             *actptr++ = T_LPAREN;
  108.         }
  109.         else if ( c==')' )
  110.         {
  111.             if ( --parens < 0 )
  112.                 error( "mismatched '()'", ACT_ERROR );
  113.             *actptr++ = T_RPAREN;
  114.         }
  115.         else if ( c==',' && !braces && !parens && Where==PATTERN )
  116.         {
  117.             /*
  118.              * found a comma outside of any braces or parens-
  119.              * this must be a regular expression seperator.
  120.              */
  121.             ungetcharacter( ',' );
  122.             break;
  123.         }
  124.  
  125.         /*
  126.          * Check if it's a regular expression:
  127.          */
  128.         else if ( c=='/' )
  129.         {
  130.             /*
  131.              * A '/' inside a pattern string starts a regular
  132.              * expression.    Inside action strings, a '/' is
  133.              * the division operator.
  134.              */
  135.             if ( Where == PATTERN )
  136.                 goto dopattern;
  137.             else
  138.                 *actptr++ = T_DIV;
  139.         }
  140.         else if ( c=='@' )
  141.         {
  142. dopattern:
  143.             /*
  144.              * Within action strings, only the '@' may be used to
  145.              * delimit regular expressions
  146.              */
  147.             *actptr++ = T_REGEXP;
  148.             ungetcharacter( c );
  149.             actptr += re_compile( actptr );
  150.         }
  151.  
  152.         /*
  153.          * symbol, string or constant:
  154.          */
  155.         else if ( alpha( c ) )
  156.         {
  157.             /*
  158.              * It's a symbol reference. Copy the symbol into
  159.              * string buffer.
  160.              */
  161.             cp = buf;
  162.             do
  163.                 *cp++ = c;
  164.             while ( (c=getcharacter()) != -1 && alphanum( c ) );
  165.             ungetcharacter( c );
  166.             *cp = 0;
  167.             /*
  168.              * Check if a keyword, builtin function or variable.
  169.              */
  170.             if ( c = iskeyword( buf ) )
  171.                 *actptr++ = c;
  172.             else if ( i = isfunction( buf ) )
  173.             {
  174.                 *actptr++ = T_FUNCTION;
  175. #if MPU68000 || MC68000
  176.                 if ( (long) actptr & 0x1) actptr++;
  177. #endif
  178.                 *((int *)actptr) = i;
  179.                 actptr += sizeof (int *);
  180.             }
  181.             else
  182.             {
  183.                 /*
  184.                  * It's a symbol name.
  185.                  */
  186.                 *actptr++ = T_VARIABLE;
  187.                 if (!(cp = (char *)findvar(buf)))
  188.                     cp = (char *)addvar(buf);
  189. #if MPU68000 || MC68000
  190.                 if ( (long) actptr & 0x1) actptr++;
  191. #endif
  192.                 *((char **)actptr) = cp;
  193.                 actptr += sizeof (char **);
  194.             }
  195.         }
  196.  
  197.         else if ( c == '"' )
  198.         {
  199.             /*
  200.              * It's a string constant
  201.              */
  202.             *actptr++ = T_STRING;
  203.             actptr = str_compile( actptr, '"' );
  204.         }
  205.         else if ( c == '\'' )
  206.         {
  207.             /*
  208.              * It's a character constant
  209.              */
  210.             *actptr++ = T_CONSTANT;
  211.             str_compile( buf, '\'' );
  212. #if MPU68000 || MC68000
  213.                 if ( (long) actptr & 0x1) actptr++;
  214. #endif
  215.             *((int *)actptr) = *buf;
  216.             actptr += sizeof (int *);
  217.         }
  218.  
  219.         else if (isdigit(c))
  220.         {
  221.             /*
  222.              * It's a numeric constant
  223.              */
  224.             *actptr++ = T_CONSTANT;
  225.             cp = buf;
  226.             do
  227.                 *cp++ = c;
  228.             while ((c=getcharacter()) != -1 && isdigit(c));
  229.             ungetcharacter( c );
  230.             *cp = 0;
  231. #if MPU68000 || MC68000
  232.                 if ( (long) actptr & 0x1) actptr++;
  233. #endif
  234.             *((int *)actptr) = atoi(buf);
  235.             actptr += sizeof (int *);
  236.         }
  237.  
  238.         /*
  239.          * unary operator:
  240.          */
  241.         else if ( c == '$' )
  242.             *actptr++ = T_DOLLAR;
  243.  
  244.         /*
  245.          * or binary operator:
  246.          */
  247.         else if ( c == '=' )
  248.         {
  249.             if ( (c=getcharacter()) == '=' )
  250.                 *actptr++ = T_EQ;
  251.             else
  252.             {
  253.                 ungetcharacter( c );
  254.                 *actptr++ = T_ASSIGN;
  255.             }
  256.         }
  257.  
  258.         else if ( c == '!' )
  259.         {
  260.             if ( (c=getcharacter()) == '=' )
  261.                 *actptr++ = T_NE;
  262.             else
  263.             {
  264.                 ungetcharacter( c );
  265.                 *actptr++ = T_LNOT;
  266.             }
  267.         }
  268.  
  269.         else if ( c == '<' )
  270.         {
  271.             if ( (c=getcharacter()) == '<' )
  272.                 *actptr++ = T_SHL;
  273.             else if ( c == '=' )
  274.                 *actptr++ = T_LE;
  275.             else
  276.             {
  277.                 ungetcharacter( c );
  278.                 *actptr++ = T_LT;
  279.             }
  280.         }
  281.  
  282.         else if ( c == '>' )
  283.         {
  284.             if ( (c=getcharacter()) == '>' )
  285.                 *actptr++ = T_SHR;
  286.             else if ( c == '=' )
  287.                 *actptr++ = T_GE;
  288.             else
  289.             {
  290.                 ungetcharacter( c );
  291.                 *actptr++ = T_GT;
  292.             }
  293.         }
  294.  
  295.         else if ( c == '&' )
  296.         {
  297.             if ( (c=getcharacter()) == '&' )
  298.                 *actptr++ = T_LAND;
  299.             else
  300.             {
  301.                 ungetcharacter( c );
  302.                 *actptr++ = T_AND;
  303.             }
  304.         }
  305.  
  306.         else if ( c == '|' )
  307.         {
  308.             if ( (c=getcharacter()) == '|' )
  309.                 *actptr++ = T_LIOR;
  310.             else
  311.             {
  312.                 ungetcharacter( c );
  313.                 *actptr++ = T_IOR;
  314.             }
  315.         }
  316.         else if ( c == '+' )
  317.         {
  318.             if ( (c=getcharacter()) == '+' )
  319.                 *actptr++ = T_INCR;
  320.             else
  321.             {
  322.                 ungetcharacter( c );
  323.                 *actptr++ = T_ADD;
  324.             }
  325.         }
  326.  
  327.         else if ( c == '-' )
  328.         {
  329.             if ( (c=getcharacter()) == '-' )
  330.                 *actptr++ = T_DECR;
  331.             else
  332.             {
  333.                 ungetcharacter( c );
  334.                 *actptr++ = T_SUB;
  335.             }
  336.         }
  337.  
  338.         /*
  339.          * punctuation
  340.          */
  341.         else if ( instr( c, "[](),;*/%+-^~" ) )
  342.             *actptr++ = c;
  343.  
  344.         else
  345.         {
  346.             /*
  347.              * Bad character in input line
  348.              */
  349.             error( "lexical error", ACT_ERROR );
  350.         }
  351.  
  352.         if ( actptr >= Workbuf + MAXWORKBUFLEN )
  353.             error( "action too long", MEM_ERROR );
  354.     }
  355.     if ( braces || parens )
  356.         error( "mismatched '{}' or '()'", ACT_ERROR );
  357.  
  358.     *actptr++ = T_EOF;
  359.  
  360.     return actptr - actbuf;
  361. }
  362.  
  363. char *str_compile( str, delim )
  364. char *str, delim;
  365. {
  366.     /*
  367.      * Compile a string from current input file into the given string
  368.      * buffer.  Stop when input character is the delimiter in "delim".
  369.      * Returns a pointer to the first character after the string.
  370.      */
  371.     int c;
  372.     char buf[ MAXLINELEN ];
  373.  
  374.     while ( (c = getcharacter()) != -1 && c != delim)
  375.     {
  376.         if ( c    == '\\' )
  377.         {
  378.             switch ( c = getcharacter() )
  379.             {
  380.             case -1: goto err;
  381.             case 'b': c = '\b'; break;
  382.             case 'n': c = '\n'; break;
  383.             case 't': c = '\t'; break;
  384.             case 'f': c = '\f'; break;
  385.             case 'r': c = '\r'; break;
  386.             case '0':
  387.             case '1':
  388.             case '2':
  389.             case '3':
  390.                 *buf = c;
  391.                 for ( c=1; c<3; ++c )
  392.                 {
  393.                     if ( (buf[c]=getcharacter()) == -1 )
  394.                         goto err;
  395.                 }
  396.                 buf[c] = 0;
  397.                 sscanf( buf, "%o", &c );
  398.                 break;
  399.             case '\n':
  400.                 if ( getcharacter() == -1 )
  401.                     goto err;
  402.             default:
  403.                 if ( (c = getcharacter()) == -1 )
  404.                     goto err;
  405.             }
  406.         }
  407.         *str++ = c;
  408.     }
  409.     *str++ = 0;
  410.  
  411.     return str;
  412. err:
  413.     sprintf( buf, "missing %c delimiter", delim );
  414.     error( buf, 4 );
  415. }
  416.  
  417. int getoken()
  418. {
  419.     switch ( Token = *Actptr++ )
  420.     {
  421.     case T_STRING:
  422.     case T_REGEXP:
  423.         Value.dptr = Actptr;
  424.         Actptr += strlen( Actptr ) + 1;
  425.         break;
  426.     case T_VARIABLE:
  427. #if MPU68000 || MC68000
  428.         if (